package gamejam.platformer;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;

import redsoxfan.gamejam.base.GameResource;

public class Map {
	public static final int TILE_SIZE = 50;
	private Point finish;
	private Tile finishTile;
	private Point start;
	private Tile[][] tiles;
	private Rectangle viewport;
	public Map(URL url, int displayWidth, int displayHeight) throws Exception {
		viewport = new Rectangle(0, 0, displayWidth, displayHeight);
		BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()));
		int rows = Integer.parseInt(br.readLine());
		int cols = Integer.parseInt(br.readLine());
		tiles = new Tile[rows][cols];
		for (int r=0; r<rows; r++) {
			char[] row = br.readLine().toLowerCase().toCharArray();
			int left = -1;
			int plat = -1;
			int span = 0;
			int chr = ' ';
			for (int c=0; c<Math.min(row.length, cols); c++) {
				char spot = row[c];
				if (left != -1) {
					if (spot == '<') {
						if (span == 0)
							throw new Exception("Moving platform of size 0 starting at row "+r+" column "+left);
						else if (chr == 'm') {
							MovingPlatform mp = new MovingPlatform(GameResource.loadImage("/gamejam/platformer/moving_sprite.png", TILE_SIZE, TILE_SIZE), TILE_SIZE * plat, TILE_SIZE * r,
									left * TILE_SIZE, (c + 1) * TILE_SIZE - 1, span);
							for (int n=left; n<=c; n++)
								tiles[r][n] = mp;
						} else if (chr == 'r') {
							MovingPlatform mp = new MovingPlatform(GameResource.loadImage("/gamejam/platformer/lava_sprite.png", TILE_SIZE, TILE_SIZE), TILE_SIZE * plat, TILE_SIZE * r,
									left * TILE_SIZE, (c + 1) * TILE_SIZE - 1, span);
							for (int n=left; n<=c; n++)
								tiles[r][n] = mp;
						} else {
							throw new Exception("Unknown moving platform type '"+chr+"' starting at row "+r+" column "+left);
						}
						left = -1;
						plat = -1;
						span = 0;
						chr = ' ';
					} else if ((chr == ' ' || chr == 'm') && spot == 'm') {
						if (plat == -1)
							plat = c;
						span++;
						chr = 'm';
					} else if ((chr == ' ' || chr == 'r') && spot == 'r') {
						if (plat == -1)
							plat = c;
						span++;
						chr = 'r';
					}
				} else if (spot == 's') {
					start = new Point(c, r);
					center(start.x * TILE_SIZE - TILE_SIZE / 2, start.y * TILE_SIZE + TILE_SIZE / 2);
				} else if (spot == 'f') {
					finish = new Point(c, r);
					finishTile = new Tile(GameResource.loadImage("/gamejam/platformer/finish_sprite.png", TILE_SIZE, TILE_SIZE), TILE_SIZE * c, TILE_SIZE * r);
				} else if (spot == 'x') {
					tiles[r][c] = new Tile(GameResource.loadImage("/gamejam/platformer/platform_sprite.png", TILE_SIZE, TILE_SIZE), TILE_SIZE * c, TILE_SIZE * r);
				} else if (spot == '>') {
					left = c;
				}
			}
		}
		br.close();
		if (start == null)
			throw new Exception("No start spot (s) in the map file");
		if (finish == null)
			throw new Exception("No finish spot (f) in the map file");
		br.close();
	}
	public void center(int cx, int cy) {
		viewport.x = Math.min(Math.max(0, cx - viewport.width / 2), tiles.length * TILE_SIZE - viewport.width);
		viewport.y = Math.min(Math.max(0, cy - viewport.height / 2), tiles[0].length * TILE_SIZE - viewport.height);
	}
	public void draw(Graphics g) {
		for (Tile[] row : tiles)
			for (Tile tile: row)
				if (tile != null && tile.getBounds().intersects(viewport))
					tile.draw(g, viewport.x, viewport.y);
		if (finishTile.getBounds().intersects(viewport))
			finishTile.draw(g, viewport.x, viewport.y);
	}
	public void drawBoundingBox(Graphics g) {
		g.setColor(Color.BLUE);
		for (Tile[] row : tiles)
			for (Tile tile: row)
				if (tile != null && tile.getBounds().intersects(viewport))
					tile.drawBoundingBox(g, viewport.x, viewport.y);
		g.setColor(Color.YELLOW);
		if (finishTile.getBounds().intersects(viewport))
			finishTile.drawBoundingBox(g, viewport.x, viewport.y);
	}
	public int getColumnCount() {
		return tiles[0].length;
	}
	public Point getFinishPosition() {
		return new Point(finish.x * TILE_SIZE, finish.y * TILE_SIZE);
	}
	public Tile getFinishTile() {
		return finishTile;
	}
	public int getRowCount() {
		return tiles.length;
	}
	public Point getStartPosition() {
		return new Point(start.x * TILE_SIZE, start.y * TILE_SIZE);
	}
	public Tile getTile(int row, int column) {
		return tiles[row][column];
	}
	public Tile getTileAtPosition(int x, int y) {
		int row = y / TILE_SIZE;
		int col = x / TILE_SIZE;
		return tiles[row][col];
	}
	public Tile getTileInViewport(int x, int y) {
		return getTileAtPosition(x + viewport.x, y + viewport.y);
	}
	public Tile[][] getTiles() {
		return tiles;
	}
	public Rectangle getViewport() {
		return viewport;
	}
	public void tick() {
		for (Tile[] row : tiles)
			for (Tile tile: row)
				if (tile != null)
					tile.tick();
	}
}
